/********************************************************************************
 * Copyright (c)2016-2020, ShenZhen WanJiaAn Technology CO.,LTD.
 * All Rights Reserved.
 *
 * File Name     : mcu_update_msg.c
 * Author        : joki.zhu
 * Date          : 2019-11-18
 *
 * Record        :
 * 1.Date        : 2019-11-18
 *   Author      : joki.zhu
 *   Modification: Created file
 ********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <pthread.h>
#include "mcu_update_msg.h"
#include "mcu_update_dev.h"
#include "UartDevConf.h"

#define FRAME_CTLNUM                 6
#define CHECK_NUM                    1
#define MAX_UARTMSG_PRINT_LEN        256
#define F2D_LEN( fLen )            ((fLen)-(FRAME_CTLNUM))           //帧长度到数据长度的转换
#define D2F_LEN( dLen )            ((dLen)+(FRAME_CTLNUM))           //数据长度到帧长度的转换
#define F2P_LEN( fLen )            ((fLen)+(4))           //帧长度到包总长度的转换

#define UARTMSG_WAITE_MSG_SLEEP_GAP (10)
#define UARTMSG_DATA_MAX_LEN     (UARTMSG_CMD_DATA_MAX_LEN + FRAME_CTLNUM)


#define UARTMSG_UPDATE_LOCK()   pthread_mutex_lock(&g_tUartMsgMutex);
#define UARTMSG_UPDATE_UNLOCK() pthread_mutex_unlock(&g_tUartMsgMutex);

#pragma  pack (push,1)                  //1字节对齐
typedef struct hiMsgFrame
{
    AV_U8                head[2];       //协议起始符
    AV_U8                len[2];        //协议帧长度: 0x04+数据长度
    AV_U8                ID;            //命令ID
    AV_U8                data[0];       //数据信息+校验符.
} MsgFrame;
#pragma pack(pop)

static AV_BOOL                   g_bUartMsgInit = AV_FALSE;
static pthread_mutex_t           g_tUartMsgMutex = PTHREAD_MUTEX_INITIALIZER;
static UartMsgRecvCallback       g_pgFnRecvMsgCbk[UARTMSG_MAX_CALLBACK_NUM];
static UARTMSG_PARM_S            g_WaiteMsg;
static UARTMSG_PARM_S*           g_pWaitMsg = NULL;
static AV_BOOL                   g_WaiteMsgReved = AV_FALSE;
static AV_BOOL                   g_debugEnable = AV_TRUE;

static AV_U8  UartMsgBufCheck(AV_U8* pBuf, AV_U16 bufLen)
{
    AV_U8 check = 0;
    AV_U16 i = 0;

    for (i = 0; i < bufLen; i++)
    {
        check ^= pBuf[i];
    }
    
    return ~check;
}

static AV_INT debug_dump(AV_U8* pbuffer, AV_U16 length, AV_CHAR* pDescription)
{
    AV_U16 i = 0;

    UARTMSGCHECK_POINTER(pDescription, AV_FAILURE);
    UARTMSGCHECK_POINTER(pbuffer, AV_FAILURE);

#if 0
    for (i = 0; i < length; i++)
    {
        MLOGD("%02X ", pbuffer[i]);
    }

    MLOGD("  %s\n", pDescription);
#else
    MLOGD("%s: ", pDescription);    
    for (i = 0; i < length; i++)
    {
        MLOGD("%02X ", pbuffer[i]);
    }
    printf("\n");
#endif

    return 0;
}
int UARTMSG_Dprintf(char* pszfmt, ...)
{
    if (NULL == pszfmt) {
        return -1;
    }

    if (g_debugEnable)
    {
        char szResponse[MAX_UARTMSG_PRINT_LEN];
        memset(szResponse, 0, MAX_UARTMSG_PRINT_LEN);

        va_list stVal;
        va_start(stVal, pszfmt);
        vsprintf(szResponse, pszfmt, stVal);
        va_end(stVal);
        printf("%s", szResponse);
    }

    return 0;
}

static AV_BOOL IsBigEndian(void)
{
    AV_U32 testData;

    testData = 0x12345678;

    if (((AV_U8*)&testData)[0] == 0x12)
    {
        return AV_TRUE;
    }
    else
    {
        return AV_FALSE;
    }
}


#if 0
void HI_UARTMSG_DebugSwitch(AV_INT s32Switch)
{
    g_debugEnable = (AV_BOOL)s32Switch;
}
#endif


/* 发送前的预处理 */
static AV_INT UARTMSG_SendFramePreprocess(MsgFrame* frame)
{
    AV_INT ret = AV_SUCCESS;

    if (!IsBigEndian())
    {
    }

    return ret;
}

static AV_INT UARTMSG_NotifyRcvData(AV_U8* pbuf, AV_U32 buf_max_len)
{
    AV_INT    s32Index = 0;
    AV_U8     check;
    MsgFrame* frame;
    AV_U16    dataLen = 0;
    AV_U16    packLen = 0;
//    HI_UARTMSG_DEBUGINFO* pDebugInfo;
    UARTMSG_PARM_S  stUartMsgParam;

    UARTMSGCHECK_EXPR(buf_max_len >= FRAME_CTLNUM, AV_FAILURE);
    UARTMSGCHECK_POINTER(pbuf, AV_FAILURE);

    frame = (MsgFrame*)pbuf;
    packLen = (frame->len[1] << 8 | frame->len[0]) & 0xffff;
    UARTMSGCHECK_EXPR(buf_max_len == packLen, AV_FAILURE);
    dataLen = F2D_LEN(packLen);
    check = UartMsgBufCheck((AV_U8 *)frame, packLen - CHECK_NUM);
    
    if (check == frame->data[dataLen])
    {
        debug_dump((AV_U8*)frame, packLen, "UARTMSG_ReciveBuf");
    }
    else
    {
        debug_dump((AV_U8*)frame, packLen, "UARTMSG_ReciveBuf");
        MLOGE("recv check error \n");
        return AV_FAILURE;
    }

    if (!IsBigEndian())
    {
        switch ((UARTMSG_MSGID_E)frame->ID)
        {
#if 0
            case HI_UARTMSG_M2S_DEBUG_REPORTINFO:
                pDebugInfo = (HI_UARTMSG_DEBUGINFO*)frame->data;
                pDebugInfo->u16RecCmd80Cnt = BigLittleSwap16(pDebugInfo->u16RecCmd80Cnt);
                pDebugInfo->u16RecCmd82Cnt = BigLittleSwap16(pDebugInfo->u16RecCmd82Cnt);
                pDebugInfo->u16RecCmd84Cnt = BigLittleSwap16(pDebugInfo->u16RecCmd84Cnt);
                pDebugInfo->u16RecCmd88Cnt = BigLittleSwap16(pDebugInfo->u16RecCmd88Cnt);
                pDebugInfo->u16RecCmd8ACnt = BigLittleSwap16(pDebugInfo->u16RecCmd8ACnt);
                pDebugInfo->u16RecCmd8CCnt = BigLittleSwap16(pDebugInfo->u16RecCmd8CCnt);
                pDebugInfo->u16RecCmdErrCnt = BigLittleSwap16(pDebugInfo->u16RecCmdErrCnt);
                pDebugInfo->u16KeyCnt = BigLittleSwap16(pDebugInfo->u16KeyCnt);
                pDebugInfo->u16PirCnt = BigLittleSwap16(pDebugInfo->u16PirCnt);
                pDebugInfo->u16WifiCnt = BigLittleSwap16(pDebugInfo->u16WifiCnt);
                pDebugInfo->u16MCUVer = BigLittleSwap16(pDebugInfo->u16MCUVer);
#endif
                break;

            default:
                break;
        }
    }

#if 0
    if (HI_UARTMSG_M2S_DEBUG_REPORTINFO == (UARTMSG_MSGID_E)frame->ID)
    {
        UARTMSG_PrintDebugInfo(frame->data, F2D_LEN(frame->len));
        return AV_SUCCESS;
    }
#endif

    UARTMSGCHECK_EXPR((int)sizeof(stUartMsgParam.data) >= F2D_LEN(packLen), AV_FAILURE); //检查MSG是否能容得下frame
    memset(&stUartMsgParam, 0, sizeof(UARTMSG_PARM_S));
    stUartMsgParam.u32MsgId = (UARTMSG_MSGID_E)frame->ID;
    stUartMsgParam.dataLen = F2D_LEN(packLen);
    memcpy(stUartMsgParam.data, frame->data, stUartMsgParam.dataLen);                     //这里只能收cmd

    if(((UARTMSG_MSGID_E)frame->ID  >=  UARTMSG_S2M_UPGRADE_DATA_INDEX_MIN &&         //需要上报给在阻塞等待的消息
        (UARTMSG_MSGID_E)frame->ID <=  UARTMSG_S2M_UPGRADE_DATA_INDEX_MAX) || 
        ((UARTMSG_MSGID_E)frame->ID  >=  UARTMSG_M2S_UPGRADE_START_ACK && 
        (UARTMSG_MSGID_E)frame->ID <=  UARTMSG_M2S_UPGRADE_END_ACK))
    {
        if ((g_pWaitMsg != NULL) && (g_WaiteMsg.u32MsgId == stUartMsgParam.u32MsgId))
        {
            memcpy(g_WaiteMsg.data, stUartMsgParam.data, stUartMsgParam.dataLen);
            g_WaiteMsg.dataLen = stUartMsgParam.dataLen;
            g_WaiteMsgReved = AV_TRUE;
        }
    }
    else                                                                                   //需要上报给回调函数的消息
    {
        for (s32Index = 0; s32Index < UARTMSG_MAX_CALLBACK_NUM; s32Index++)
        {
            if (g_pgFnRecvMsgCbk[s32Index] != NULL)
            {
                g_pgFnRecvMsgCbk[s32Index](&stUartMsgParam);
            }
        }
    }

    return AV_SUCCESS;
}

int UartMsgInit(void)
{
    AV_INT s32Ret = AV_FAILURE;

    UARTMSG_UPDATE_LOCK();

    if (AV_TRUE != g_bUartMsgInit)
    {
        memset(g_pgFnRecvMsgCbk, 0, sizeof(g_pgFnRecvMsgCbk));
        s32Ret = UartDevInit(UARTMSG_NotifyRcvData);
    }
    if (AV_SUCCESS == s32Ret)
    {
        g_bUartMsgInit = AV_TRUE;
    }

    UARTMSG_UPDATE_UNLOCK();

    return s32Ret;    
}


int UartMsgRegisterRecv(UartMsgRecvCallback pRecvCallback)
{
    AV_INT ret = AV_FAILURE;
    AV_INT index = 0;
    AV_INT idleIndex = -1;

    UARTMSGCHECK_POINTER(pRecvCallback, AV_FAILURE);
    UARTMSGCHECK_EXPR(g_bUartMsgInit == AV_TRUE, AV_FAILURE);

    UARTMSG_UPDATE_LOCK();

    for (index = 0; index < (int)(sizeof(g_pgFnRecvMsgCbk) / sizeof(UartMsgRecvCallback)); index++)
    {
        if (g_pgFnRecvMsgCbk[index] == NULL)
        {
            idleIndex = index;
        }
        else if (g_pgFnRecvMsgCbk[index] == pRecvCallback)
        {
            UARTMSG_UPDATE_UNLOCK();
            MLOGD("This function has been registered !\n");
            return ret;
        }
    }

    if ((idleIndex >= 0 ) && (idleIndex < UARTMSG_MAX_CALLBACK_NUM))
    {
        g_pgFnRecvMsgCbk[idleIndex] = pRecvCallback;
        ret = AV_SUCCESS;
    }

    UARTMSG_UPDATE_UNLOCK();
    return ret;
    
}

int UartMsgUnRegisterRecv(UartMsgRecvCallback pRecvCallback)
{
    AV_INT ret   = AV_FAILURE;
    AV_INT index = 0;

    UARTMSGCHECK_POINTER(pRecvCallback, AV_FAILURE);
    UARTMSGCHECK_EXPR(g_bUartMsgInit == AV_TRUE, AV_FAILURE);

    UARTMSG_UPDATE_LOCK();

    for (index = 0; index < (int)(sizeof(g_pgFnRecvMsgCbk) / sizeof(UartMsgRecvCallback)); index++)
    {
        if (g_pgFnRecvMsgCbk[index] == pRecvCallback)
        {
            g_pgFnRecvMsgCbk[index] = NULL;
            ret = AV_SUCCESS;
            break;
        }
    }

    UARTMSG_UPDATE_UNLOCK();
    return ret;
}

int UartMsgSendData(UARTMSG_MSGID_E msgId, AV_U8 *pData, AV_U16 dataLen)
{
    AV_INT s32Ret = AV_SUCCESS;
    AV_U16 packLen = D2F_LEN(dataLen);

#ifndef JOKI_DEBUG
    UARTMSGCHECK_EXPR(g_bUartMsgInit == AV_TRUE, AV_FAILURE);
#endif    
    UARTMSGCHECK_EXPR(dataLen < UARTMSG_DATA_MAX_LEN, AV_FAILURE);

    MsgFrame* frame = (MsgFrame*)malloc(sizeof(MsgFrame) + dataLen + CHECK_NUM ); //协议头 + 数据 + 校验字节
    UARTMSGCHECK_POINTER(frame, AV_FAILURE);

    frame->head[0] = UARTMSG_MSGDATA_HEAD & 0xff;
    frame->head[1] = UARTMSG_MSGDATA_HEAD >> 8 & 0xff;

    frame->len[0] = D2F_LEN(dataLen) & 0xff;
    frame->len[1] = D2F_LEN(dataLen) >> 8 & 0xff;
    
    frame->ID = (AV_U8)msgId;

    memcpy(frame->data, pData, dataLen);

    frame->data[dataLen] = UartMsgBufCheck((AV_U8 *)frame, packLen - CHECK_NUM);

#ifndef JOKI_DEBUG
    s32Ret = UartDevSendBuf((AV_U8*)frame, packLen);
    if (s32Ret != AV_SUCCESS)
    {
        MLOGE(" Send frame fail \n ");
    }
#endif

    debug_dump((AV_U8*)frame, packLen, "UARTMSG_SendBuf");
    
    if (frame)
    {
        free(frame);
    }

    return s32Ret;    
}

int UartMsgSendMsg(UARTMSG_PARM_S *pSendMsg)
{
    AV_INT ret = AV_SUCCESS;

    UARTMSGCHECK_POINTER(pSendMsg, AV_FAILURE);

    UARTMSG_UPDATE_LOCK();
    ret = UartMsgSendData(pSendMsg->u32MsgId, pSendMsg->data, pSendMsg->dataLen);
    UARTMSG_UPDATE_UNLOCK();

    return ret;
}

int UartMsgSendMsgAndWaitMsg(UARTMSG_PARM_S *pSendMsg, UARTMSG_PARM_S *pWaitMsg, AV_U32 timeoutMs)
{
    AV_INT ret = AV_SUCCESS;
    AV_U32 sleepTime = 0;

    UARTMSGCHECK_POINTER(pSendMsg, AV_FAILURE);
    UARTMSGCHECK_POINTER(pWaitMsg, AV_FAILURE);
    UARTMSGCHECK_EXPR((pSendMsg->dataLen <=  UARTMSG_CMD_DATA_MAX_LEN), AV_FAILURE);
    UARTMSGCHECK_EXPR((pWaitMsg->dataLen <=  UARTMSG_CMD_DATA_MAX_LEN), AV_FAILURE);

    UARTMSG_UPDATE_LOCK();
    g_WaiteMsgReved = AV_FALSE;
    g_pWaitMsg = &g_WaiteMsg;
    memset(&g_WaiteMsg, 0, sizeof(g_WaiteMsg));
    memcpy(&g_WaiteMsg, pWaitMsg, sizeof(g_WaiteMsg));
    ret = UartMsgSendData(pSendMsg->u32MsgId, pSendMsg->data, pSendMsg->dataLen);

    if (ret == AV_SUCCESS)
    {
        while ((g_WaiteMsgReved == AV_FALSE) && (sleepTime < timeoutMs))
        {
            sleepTime += UARTMSG_WAITE_MSG_SLEEP_GAP;
            usleep(UARTMSG_WAITE_MSG_SLEEP_GAP);
        }

        if (g_WaiteMsgReved == AV_FALSE)
        {
            ret = AV_FAILURE;
            MLOGE("wait message[0x%02X] ack timeout(%d) \n", g_pWaitMsg->u32MsgId, timeoutMs);
        }

        memcpy((void*)pWaitMsg->data, g_WaiteMsg.data, g_WaiteMsg.dataLen);
        pWaitMsg->dataLen = g_WaiteMsg.dataLen;
        
    }

    g_pWaitMsg = NULL;
    UARTMSG_UPDATE_UNLOCK();

    return ret;
}

int UartMsgDeinit(void)
{
    AV_INT s32Ret = AV_SUCCESS;
    UARTMSG_UPDATE_LOCK();

    if (AV_FALSE != g_bUartMsgInit)
    {
        s32Ret = UartDevDeinit();
        g_bUartMsgInit = AV_FALSE;
    }

    UARTMSG_UPDATE_UNLOCK();
    return s32Ret;
}

